package com.sardine.base.esm.binding;

import com.sardine.base.esm.builder.EsmMapperAnnotationBuilder;
import com.sardine.base.esm.exception.EsmBindingException;
import com.sardine.base.esm.session.Configuration;
import com.sardine.base.esm.session.EsmSession;
import org.apache.ibatis.binding.BindingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 上海京东到家元信信息技术有限公司<br>
 * Created with IntelliJ IDEA.
 * Date:2017/5/23
 * Time:16:24
 * annotation 映射注册
 * @author daifeng<br>
 *         daifeng@imdada.cn
 * @since JDK 1.7 <br>
 * Copyright (c) 2017 imdada System Incorporated All Rights Reserved.
 */
public class EsmMapperRegistry {
    private static final Logger logger = LoggerFactory.getLogger(EsmMapperRegistry.class);
    private Configuration configuration;
    private final Map<Class<?>,EsmMapperProxyFactory<?>> knownMappers=new HashMap<>();

    public EsmMapperRegistry(Configuration configuration) {
        this.configuration = configuration;
    }

    public <T> T getMapper(Class<T> type, EsmSession esmSession) {
        //从map中获取一个接口代理对象
        final EsmMapperProxyFactory<T> mapperProxyFactory = (EsmMapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new EsmBindingException(" type" + type + " is not known to this MapperRegistry.");
        }
        try {
            //创建接口代理对象的实例
            return mapperProxyFactory.newInstance(esmSession);
        } catch (Exception e) {
            throw new EsmBindingException("Error getting mapper instance. Cause: " + e, e);
        }
    }

    public <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }

    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (hasMapper(type)) {
                throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
            }
            boolean loadCompleted = false;
            try {
                //注册接口和代理工厂
                knownMappers.put(type, new EsmMapperProxyFactory<T>(type));
                //解析annotation 的数据
                EsmMapperAnnotationBuilder parser= new EsmMapperAnnotationBuilder(configuration,type);
                //解析
                parser.parse();
                //解析annotation
                loadCompleted = true;
            } finally {
                if (!loadCompleted) {
                    knownMappers.remove(type);
                }
            }
        }
    }
}
